
#include "transfer/SignalStorage.h"

#include "transfer/ReadWriteLock.h"

namespace ecarx::transfer::storage {

using namespace transfer::lock;

static RWLock lock;

const std::optional<Signal> SignalPool::get(int32_t signalId) const {
    AutoRead readLock(&lock);
    auto iter = mCache.find(signalId);
    std::optional<Signal> result;
    if (iter != mCache.end()) {
        result = iter->second;
    }
    return result;
}

void SignalPool::put(const std::vector<Signal>& signals,std::vector<int32_t> & changed) {
    AutoWrite wirteLocl(&lock);
    changed.reserve(signals.size());
    for (auto& signal : signals) {
        auto iter = mCache.find(signal.signalId);

        if (iter != mCache.end()) {
            if(signal.mode == NotifyMode::Direct || !compare(signal, iter->second)){
                iter->second.value = signal.value;
                changed.emplace_back(signal.signalId);
            }
        } else {
            mCache.insert(std::pair<uint32_t,Signal>(signal.signalId, signal));
            changed.emplace_back(signal.signalId);
        }
    }
}

inline bool SignalPool::compare(const Signal& newSignal, const Signal& old) {
    size_t size = 0;
    if ((size = newSignal.value.int32Values.size()) != 0) {
        if (newSignal.value.int32Values.size() != old.value.int32Values.size()) {
            return false;
        }
        for (size_t i = 0; i < size; ++i) {
            if (newSignal.value.int32Values[i] != old.value.int32Values[i]) {
                return false;
            }
        }
    } else if ((size = newSignal.value.int64Values.size()) != 0) {
        if (newSignal.value.int64Values.size() != old.value.int64Values.size()) {
            return false;
        }
        for (size_t i = 0; i < size; ++i) {
            if (newSignal.value.int64Values[i] != old.value.int64Values[i]) {
                return false;
            }
        }
    } else if ((size = newSignal.value.floatValues.size()) != 0) {
        if (newSignal.value.floatValues.size() != old.value.floatValues.size()) {
            return false;
        }
        for (size_t i = 0; i < size; ++i) {
            if (newSignal.value.floatValues[i] != old.value.floatValues[i]) {
                return false;
            }
        }
    } else if ((size = newSignal.value.bytes.size()) != 0) {
        if (newSignal.value.bytes.size() != old.value.bytes.size()) {
            return false;
        }
        for (size_t i = 0; i < size; ++i) {
            if (newSignal.value.bytes[i] != old.value.bytes[i]) {
                return false;
            }
        }
    } else if ((size = newSignal.value.stringValue.size()) != 0) {
        return strcmp(newSignal.value.stringValue.c_str(), old.value.stringValue.c_str());
    }
    return true;
}

}  // namespace ecarx::net::storage
